/**
 * Created by hjg on 2018/8/20.
 * http工具类
 */

import {Injectable} from '@angular/core';
import {Http, Headers, RequestOptions} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {PublicService} from "../common/public.service";

@Injectable()
export class HttpService {

  constructor(public http: Http,
              public pub: PublicService) {
  }

  /**
   * get请求
   * @param url 地址
   * @param connector 连接符（?|&）
   * @param paramObj 参数
   * @param showLoading 是否显示加载过程
   * @returns {Promise<TResult|TResult2|TResult1>}
   */
  public get(url: string, connector: string, paramObj: any, showLoading: boolean) {
    if (!this.pub.networkConnect()) {
      this.pub.presentAlert("当前网络不可用，请检查网络设置！");
      return;
    }
    let loading = null;
    if (showLoading) {
      loading = this.pub.presentLoadingDefault();
      loading.present();
    }
    return this.http.get(url + this.toQueryString(connector, paramObj))
      .toPromise()
      .then(res => this.handleSuccess(res.json(), loading))
      .catch(error => this.handleError(error, loading));
  }

  /**
   * post请求
   * @param url
   * @param connector
   * @param paramObj
   * @param showLoading
   * @returns {Promise<TResult|TResult2|TResult1>}
   */
  public post(url: string, connector: string, paramObj: any, showLoading: boolean) {
    if (!this.pub.networkConnect()) {
      this.pub.presentAlert("当前网络不可用，请检查网络设置！");
      return;
    }
    let loading = null;
    if (showLoading) {
      loading = this.pub.presentLoadingDefault();
      loading.present();
    }
    let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
    return this.http.post(url, this.toBodyString(paramObj, connector), new RequestOptions({headers: headers}))
      .toPromise()
      .then(res => this.handleSuccess(res.json(), loading))
      .catch(error => this.handleError(error, loading));
  }


  public postBody(url: string, paramObj: any) {
    if (!this.pub.networkConnect()) {
      this.pub.presentAlert("当前网络不可用，请检查网络设置！");
      return;
    }
    const loading = this.pub.presentLoadingDefault();
    loading.present();
    let headers = new Headers({'Content-Type': 'application/json'});
    return this.http.post(url, paramObj, new RequestOptions({headers: headers}))
      .toPromise()
      .then(res =>
        this.handleSuccess(res.json(), loading))
      .catch(error =>
        this.handleError(error, loading));
  }

  /**
   * 请求成功处理
   * @param result
   * @param loading
   * @returns {any}
   */
  private handleSuccess(result, loading: any) {
    if (loading) {
      loading.dismiss();
    }
    if (result && !result.success) {//由于和后台约定好,所有请求均返回一个包含success,msg,data三个属性的对象,所以这里可以这样处理
      //alert(result.msg);//这里使用ToastController
    }
    return result;
  }

  /**
   * 请求失败处理
   * @param error
   * @param loading
   * @returns {{success: boolean, msg: string}}
   */
  private handleError(error: Response | any, loading: any) {
    if (loading) {
      loading.dismiss();
    }
    let msg = '请求失败';
    if (error.status == 0 && error.type == 3) {
      msg = '网络错误';
    } else if (error.status == 400) {
      msg = '请求无效';
    } else if (error.status == 404) {
      msg = '请求资源不存在';
    } else if (error.status == 500) {
      msg = '服务器异常';
    } else if (error.status == 408) {
      msg = '服务器超时';
    }
    if (error.msg) {
      msg = error.msg;
    }
    return {success: false, msg: msg};
  }

  /**
   * @param obj　参数对象
   * @return {string}　参数字符串
   * @example
   *  声明: var obj= {'name':'小军',age:23};
   *  调用: toQueryString(obj);
   *  返回: "?name=%E5%B0%8F%E5%86%9B&age=23"
   */
  public toQueryString(connector, obj) {
    let ret = [];
    for (let key in obj) {
      key = encodeURIComponent(key);
      let values = obj[key];
      if (values && values.constructor == Array) {//数组
        let queryValues = [];
        for (let i = 0, len = values.length, value; i < len; i++) {
          value = values[i];
          queryValues.push(this.toQueryPair(key, value));
        }
        ret = ret.concat(queryValues);
      } else { //字符串
        ret.push(this.toQueryPair(key, values));
      }
    }
    return connector + ret.join('&');
  }

  /**
   *
   * @param obj
   * @return {string}
   *  声明: var obj= {'name':'小军',age:23};
   *  调用: toQueryString(obj);
   *  返回: "name=%E5%B0%8F%E5%86%9B&age=23"
   */
  private toBodyString(obj, connector) {
    let ret = [];
    for (let key in obj) {
      key = encodeURIComponent(key);
      let values = obj[key];
      if (values && values.constructor == Array) {//数组
        let queryValues = [];
        for (let i = 0, len = values.length, value; i < len; i++) {
          value = values[i];
          queryValues.push(this.toQueryPair(key, value));
        }
        ret = ret.concat(queryValues);
      } else { //字符串
        ret.push(this.toQueryPair(key, values));
      }
    }
    return connector + ret.join('&');
  }

  /**
   * 处理结果集
   * @param key
   * @param value
   * @returns {any}
   */
  private toQueryPair(key, value) {
    if (typeof value == 'undefined') {
      return key;
    }
    return key + '=' + encodeURIComponent(value === null ? '' : String(value));
  }
}
